PressNext Live 1.9.3
====================

Version 1.9.3 (Remove starting "The")
-----------------------------------------
A third renaming command in the "Batch format lyrics" menu: "Remove
starting \"The\"…". Pick any files and a leading "The" is removed from each
name, together with the space after it, so "The Beatles - Yesterday.wav"
becomes "Beatles - Yesterday.wav". Useful when half the repertoire piles
up under T in Finder.

Only a real leading word is removed: "The" must be followed by a space,
so "Theatre of Pain.wav" and "Theremin Song.mp3" are left alone. Case does
not matter — "THE", "the" and "The" are all handled. Files that do not
start with "The" are reported as skipped rather than silently ignored.

Two files cannot end up fighting for the same name: names produced during
the run are reserved as they are planned, so if both "The Cure.wav" and
"the Cure.wav" are selected, the first is renamed and the second is
skipped as a conflict instead of overwriting it.

The three renaming commands now share one skeleton (choose files, build
the plan, confirm, apply), so confirmation, conflict protection, the
summary and the log behave identically in all of them.

Version 1.9.2 (word-order-independent matching, "The" ignored, unmatched files reported)
-------------------------------------------------------------------------------------------
Three changes to "Match lyrics names to tracks…".

1. Files that match nothing are now reported. Previously they were
   skipped silently, so after a run there was no way to tell what still
   needed sorting out by hand. They now appear in the summary and in the
   log with the reason "no matching backing track".

2. Names are also compared as SETS OF WORDS, ignoring order. This is what
   makes "Yesterday - Beatles.png" find "Beatles - Yesterday.wav", and
   "Yesterday.png" (just the song title, no artist) find
   "Beatles - Yesterday E >>8.wav".

   Note that working out which part of a name is the artist and which is
   the song is not possible from a filename alone — nothing distinguishes
   "Beatles" from "Yesterday" but a music database. It is also not
   needed: the target name is always taken from the backing track in
   full, so the roles never have to be known.

3. "The" is ignored during comparison, anywhere in the name, so
   "The Beatles - Come Together" and "Beatles - Come Together" are the
   same thing. This affects comparison only — the target name is still
   copied from the track exactly as it is, "The" included.

Matching now works in three stages, from the most reliable to the most
permissive, and each later stage always scores below the earlier one:
  1. the names are identical;
  2. one name is the beginning of the other, ending on a word boundary
     ("Yesterday" finds "Yesterday E >>8", while "creep" does not attach
     itself to "Creeper");
  3. every word of the shorter name appears in the longer one, in any
     order.

Ambiguity is only detected within a single stage: if two tracks match
equally well at the same stage, the file is skipped and reported. A
stronger stage always beats a weaker one, so where one track matches by
its beginning and another by word set, the first wins without being
treated as ambiguous. Very short names (under 3 characters) are not
matched by word set at all, as they would fit too many things.

Since the list of skipped files can get long, the summary window shows
the first 20 and says how many more there are; the full list is always in
PressNextLive-batch-log.txt next to the files.

Version 1.9.1 (crash after "Match lyrics names to tracks" fixed)
-------------------------------------------------------------------
Renaming worked, but the app crashed right after it. This is the same
failure already seen with batch formatting in 1.8.4: the summary window
was being drawn immediately after the work finished, inside the menu
handler.

The rename summary now goes through the same deferred mechanism as the
formatting summary — it is shown on a separate, later idle tick (about
0.4 s), giving the event loop time to cycle before AppKit draws the
dialog.

Renaming also writes PressNextLive-batch-log.txt into the folder it is
working on: the start of the run, every individual rename with its result,
the totals, and the moments before and after the summary is shown. If a
crash ever happens again, the last line of that file says exactly how far
the work got.

Nothing about the renaming itself changed — the same matching rules, the
same confirmation before any change, the same protection against
overwriting existing files.

Version 1.9.0 (batch renaming: match lyrics names, reset manual sorting)
----------------------------------------------------------------------------
Two renaming commands were added at the bottom of the "Batch format
lyrics" menu. Both only rename files — they never create or delete
anything, both show what they are about to do and ask for confirmation
first, and neither ever overwrites an existing file.

"Match lyrics names to tracks…"
Pick a folder holding backing tracks and lyrics files. Every lyrics file
(PNG, JPG, JPEG, PDF, DOCX, TXT) is renamed to exactly match the name of
its backing track (MP3, WAV), which is what PressNext Live needs in order
to show the lyrics when the song plays. For example, "yesterday.jpg" next
to "Yesterday E >>8.wav" becomes "Yesterday E >>8.jpg".

Matching ignores case, apostrophes, dashes, underscores and punctuation,
so "dont-look-back.png" finds "Don't Look Back G >>5.wav". A lyrics name
matches when it is the beginning of a track name (or the other way
round), and the match must end on a word boundary — so "creep.jpg" will
not attach itself to "Creeper F.wav". Where several tracks match equally
well, the longer match wins; if they are still tied, the file is skipped
and listed as ambiguous rather than renamed by guesswork.

"Reset manual song sorting…"
Pick any files and the first 3 characters are removed from each name —
the reverse of the numbering added for a set list, so "01 Yesterday.wav"
becomes "Yesterday.wav". Files whose name would be left empty are skipped,
as are those whose target name is already taken.

Both commands end with a summary: how many files were renamed, and the
list of anything skipped with the reason (target name already exists,
ambiguous match, name too short, or the system refused the rename).

Version 1.8.4 (batch log + deferred summary dialog)
------------------------------------------------------
The crash at the end of batch formatting survived 1.8.3, where files were
already being processed one per event-loop tick. That ruled out the
memory explanation: memory is now released between files, yet the crash
stayed in exactly the same place.

The one thing common to every version that crashed was the summary
window, which was drawn immediately after the last image was rendered.
So:

1. The summary is no longer shown at that moment. It is deferred to a
   separate, later idle tick (about 0.4 s), giving the event loop time to
   cycle fully and clean up after rendering before AppKit starts drawing
   the dialog window.

2. A log was added: a file named PressNextLive-batch-log.txt is written
   next to the results, in the chosen save folder. It records the start
   of the run, the start and result of each file, the moment all files
   are done, the moment before the summary is shown, and the moment after
   it is closed.

The log exists because a crash kills the app silently. The last line
tells you immediately how far the work got:
  "all files done" as the last line — the crash is between the end of
      processing and the summary;
  "about to show summary dialog" as the last line — the crash is on the
      summary window itself;
  "summary dialog closed" as the last line — processing and summary both
      completed, so the crash is after them, outside the batch code.

Every file is saved as the run proceeds, so even on a crash the results
stay on disk — only the summary display is lost.

Version 1.8.3 (the correct fix for the batch formatting crash)
------------------------------------------------------------------
In 1.8.2 the end-of-run crash was treated with a manual autorelease pool
(NSAutoreleasePool) around each file. That must not be done: the JXA
bridge holds its own references to objects inside the pool, and draining
it crashes the app — immediately, before even the first file is
processed. That approach was removed completely.

The diagnosis of the cause was unchanged and correct: rendering one image
creates tens of megabytes of temporary AppKit objects (an NSImage for the
1400x1960 canvas, twice as large on each side on a Retina display, its
TIFF representation, and up to ten JPEG variants while fitting the size
budget). Such objects are released when control returns to the event
loop. While the whole run was one long loop inside a menu handler, that
return never happened until the very end — memory grew with each file and
the app crashed at the end of the run.

Batch formatting now runs ONE FILE PER IDLE TICK. The "Start formatting"
command only queues the work and returns immediately; the ticks are
driven by idle() — the same mechanism already used for deferred seeking,
volume changes and QuickTime window placement. Between files control
returns to the event loop, which releases the temporary objects itself.
No manual memory management anywhere.

The verse, chorus and bridge colors are deliberately recreated on every
step: it is cheap, and it means no reference to an AppKit object survives
between ticks, where the event loop may already have released it.

Also: starting a run while one is in progress is ignored, a failure on
one file does not stop the queue (the file goes into the failed list, as
before), and quitting the app cancels the run.

Version 1.8.2 (attempted fix for the crash after batch formatting)
----------------------------------------------------------------------
Superseded by 1.8.3 — see above. The manual autorelease pool introduced
here crashed the app immediately on "Start formatting" and was removed.

Version 1.8.1 (obsolete installer message removed)
------------------------------------------------------
The informational "Done" dialog was removed from Install.command — the
one about coexisting with the original PressNext, about SongLyr and
SongLL, and about Command Line Tools and Xcode not being needed. It had
long since stopped being relevant.

Installation now finishes silently: the app simply launches. The error
message for an incompletely unpacked archive is still there — it is still
needed.

Version 1.8.0 (English menus by default, switchable to Russian)
------------------------------------------------------------------
The interface is now English by default. The language is switched in
"File -> Menu language" (English / Russian). The choice is remembered
between launches.

Menus, left to right:
  File                 — Menu language
  Pedalboard app       — the app activated after a song starts
  Lyrics               — which side of the screen the lyrics window takes
  Player view          — how the QuickTime window is shown
  Hotkeys              — key assignments
  Batch format lyrics  — batch lyrics formatting

Not only the menus were translated, but also every submenu, confirmation
dialog, prompt in the system file and folder pickers, error message and
the batch formatting summary — 67 strings in each language.

The language names in the submenu ("English" and "Русский") are
deliberately left untranslated: as everywhere in macOS, each language is
labelled in itself, so it can be found without being able to read the
current interface language.

Switching the language rebuilds the whole menu bar. This is necessary
because menu item titles are set once when the menus are created, and the
ordinary state update (checkmarks, dynamic labels) does not change them.
So on a switch all previously added menus are removed and created again,
with text in the new language.

The Russian song-structure marker words ("припев", "куплет", "бридж" and
so on), used to recognise the structure of lyrics during batch
formatting, have nothing to do with the interface language and always
work, whichever menu language is selected.

Version 1.7.0 (choice of QuickTime window view)
--------------------------------------------------
A new "Player view" menu with two options:
  Whole window                   — the whole QuickTime window is visible
                                    (the 1.4.0 behaviour).
  Top of window (scrubber only)  — half the window hangs below the screen
                                    edge, leaving only the top half
                                    visible: the title bar and the
                                    scrubber with the timing (the 1.5.0
                                    behaviour, and the current default).

The choice applies immediately, without a restart, and is remembered
between launches — like the lyrics side. Unlike the "Automatically place
QuickTime" toggle removed in 1.5.0, this is not an on/off switch but a
choice between two options (the way the lyrics side already works in the
"Lyrics" menu) — placement itself is always on, so there is nothing to
break.

Version 1.6.0 (QuickTime volume hotkeys)
--------------------------------------------
Two new actions in the "Hotkeys" menu:
  QuickTime volume down 2 dB  — Cmd+Down by default
  QuickTime volume up 2 dB    — Cmd+Up by default

Document volume in QuickTime Player is a linear value (1.0 = 100%, and
QuickTime itself allows going higher — up to 3.0 = 300% gain), not
decibels. A 2 dB step is converted into a multiplier every time using the
standard amplitude formula, 10^(dB/20) — roughly x1.259 for louder and
x0.794 for quieter — and applied to the CURRENT volume rather than added
as a fixed number. This means the step is always proportional to the
current volume, as a logarithmic loudness scale requires: the same sense
of "how much louder it got" at quiet and loud levels alike.

Several rapid presses add up into one total dB delta and are applied in a
single call to QuickTime (the same scheme already used for seeking, where
several arrow presses combine into one command). The upper limit is 2.0
(about +6 dB above the nominal 100%): enough headroom for a quiet
recording, without the risk of a sudden, unexpectedly loud jump on stage.
The lower limit is 0 (silence).

The volume is changed on the document of the current song (using the same
document lookup already used for seeking and pausing) — the commands go
straight to QuickTime Player, without System Events, so they are
untouched by the permissions story from version 1.4.0.

Version 1.5.0 (only the top of the QuickTime window again; "Player" menu removed)
------------------------------------------------------------------------------------
After the fix in 1.4.0 the QuickTime window placement finally worked.
Then two simplifications, from real use.

1. The QuickTime window now moves down by exactly half its height — the
top half is visible (title bar and the scrubber with the timing), the
bottom half (transport buttons and volume) goes below the screen edge.
The zone itself (its own half of the screen, opposite the lyrics, full
width) is unchanged; only the vertical position inside it changed.

2. The "Player" menu was removed entirely — together with the
"Automatically place QuickTime" toggle (switching it off crashed the app;
the bug itself was not investigated, since the toggle was being dropped
anyway) and the "Place QuickTime window now" command. Automatic placement
is the only mode, always on, with no settings left for it.

Version 1.4.0 (the real cause fixed: the permission went to the wrong process)
---------------------------------------------------------------------------------
Window placement had not worked in any version from 1.2.0 to 1.3.1,
despite "Accessibility" being explicitly enabled for PressNext Live,
checked repeatedly and confirmed after a restart.

The cause was in HOW the AppleScript was executed. Until this version,
window placement (both lyrics and QuickTime) went through
`do shell script "osascript -e '...'"` — that is, PressNext Live launched
a SEPARATE /usr/bin/osascript process, and it was THAT process, not
PressNext Live, that talked to System Events. But an Accessibility
permission belongs to the specific process sending the Apple event, so
what was actually required was permission for /usr/bin/osascript, not for
PressNext Live. Since osascript is not an .app bundle, that permission
does not even appear in the list to be granted by hand — so enabling and
disabling PressNext Live there changed nothing.

Commands that do NOT require Accessibility (opening a file in QuickTime
Player, playing it, activating the DAW) had their own separate consent
prompts, which had evidently been granted — which is why playback worked
while window management through System Events did not.

Both places that need System Events (the lyrics window and the QuickTime
window) now talk to it DIRECTLY from the PressNext Live process, through
the native JXA bridge (Application('System Events') right in the code),
with no child osascript process. The Apple event is sent by PressNext
Live itself, so the permission already granted to it finally applies.

DAW activation, file opening and playback are unchanged — they never used
System Events (only plain commands to applications), so nothing was
broken there and nothing needed touching.

Version 1.3.1 (diagnostics instead of a generic error message)
------------------------------------------------------------------
The "Place QuickTime window now" command, when placement failed, began
showing a precise diagnostic instead of a generic phrase: whether System
Events saw no QuickTime process at all, saw processes but no windows, or
found the window but had a specific step (reading the size, resizing,
repositioning) fail with a specific AppleScript error number and text.
This is what identified the real cause fixed in 1.4.0.

Version 1.3.0 (QuickTime: a dedicated screen zone instead of a strip)
------------------------------------------------------------------------
The earlier approach — shrinking the QuickTime window into a narrow strip
and hiding most of it below the screen edge — turned out to be
unreliable. Instead of fighting it further, the scheme was changed
completely: the QuickTime window gets its OWN half of the screen, the one
opposite the lyrics window, and is shown there in full. If the lyrics are
on the left, QuickTime gets the right half, and vice versa; if the lyrics
occupy a whole second display, QuickTime gets the whole main screen.
Since the two zones are separate, non-overlapping halves, the windows can
never cover each other.

Version 1.2.2 (QuickTime strip: reliability and minimum height)
-------------------------------------------------------------------
Superseded by 1.3.0. The window height was always forced down to the
chosen value rather than only when macOS refused to move the window off
the bottom edge, the window was located as the front window of the
process, and a short burst of retries was added right after a song opens,
in case QuickTime rearranges its own window a moment later.

Version 1.2.1 (QuickTime strip at the bottom of the screen)
---------------------------------------------------------------
Superseded by 1.3.0. The QuickTime window took the left edge and width of
the lyrics window and moved below the bottom screen edge, leaving only the
title bar, scrubber and timing visible.

Version 1.1.3 (image margins and chorus detection)
------------------------------------------------------
Batch formatting:
- Margins of the finished image reduced to 8 px on each side (they were
  70 px horizontally and 90 px vertically). The 160 pt font size ceiling
  was also removed; it had left hundreds of pixels of emptiness around
  short lyrics. The font size is now chosen fractionally and the text
  fills the frame. Leftover height (when the font size is limited by line
  width) is distributed into line spacing instead of turning into empty
  margins. Side margins stay wider than 8 px on short lines — the line is
  simply shorter than the frame; the app will not stretch the letters.
- Chorus and bridge detection reworked. Fixed:
  * markers are now parsed rather than matched against a rigid pattern:
    [Chorus], (CHORUS 2), "Chorus:", "Chorus x2", "Chorus (2 times)",
    "Refrain" are all understood, as is "Chorus: first line" where the
    lyrics start on the same line as the marker;
  * files without blank lines used to count as a single stanza, so a
    chorus was never found in them. A marker now splits the text into
    stanzas itself, and where there are no markers the app looks for
    repeating blocks of lines and cuts the song along them;
  * a lone "Chorus" line between verses is now understood as "the chorus
    is sung here" and produces +CHORUS. It used to mark the verse that
    followed it as the chorus;
  * repeats are searched across the whole song, not only below the
    marker: an unmarked chorus above a marked one is recognised too;
  * the tolerance for "the same chorus sung slightly differently" now
    depends on stanza length instead of always being 15 characters. Short
    stanzas no longer merge, and in long ones a single altered line no
    longer breaks detection;
  * "Instrumental", "Solo", "Intro", "Coda" and verse numbering ("1.",
    "2)") are stripped from the text and simply separate stanzas.

Version 1.1.2 (batch formatting)
------------------------------------
Chorus/bridge detection rules in batch formatting reworked (details in
the "Batch format lyrics menu" section below):
- a [Chorus]/[Bridge] marker (case-insensitive) marks the first
  appearance; all later repeats of that text are found across the whole
  song — even unmarked ones — and collapsed into +CHORUS/+BRIDGE at the
  end of the previous line rather than on a line of their own;
- a repeat with small differences (up to 15 characters per paragraph)
  collapses into +VAR CHORUS/+VAR BRIDGE instead of +CHORUS/+BRIDGE;
- if only the chorus or only the bridge is marked, the missing one is
  found automatically from text repeats; if neither is marked, all
  repeats found are treated as the chorus;
- if there are no markers and no repeats, paragraphs are coloured in
  rotation — white, light blue, light green — for readability.

Version 1.1.1 (fix)
-----------------------
Fixed an intermittent crash when choosing a song or file (typing in the
system dialog), especially when switching keyboard layout while typing in
the dialog on macOS Tahoe. The cause was the global key monitor, which
watched keystrokes system-wide and stayed active on top of the modal
system file dialog. The global monitor is now paused while a dialog is
shown ("Choose song", target app selection, file/folder selection in
batch formatting) and re-enabled as soon as it closes. Ordinary assigned
keys (including Cmd+Q) keep working as before.

Installation
------------
1. Unpack the ZIP archive completely.
2. Double-click Install.command.
3. If macOS blocks it, right-click Install.command, choose "Open" and
   confirm.

The app is installed to ~/Applications/PressNext Live.app. Xcode and
Command Line Tools are not needed. PressNext Live has its own name and
identifier, so it can be installed alongside SongLyr and SongLL. Do not
run these players at the same time, though: they control the same system
applications.

PressNext Live is a separate fork of the original PressNext (its own
install path, its own bundle identifier, its own settings). If PressNext
is already installed, it is not affected: both can be kept side by side,
with separate settings stores. As with SongLyr/SongLL, do not run
PressNext and PressNext Live at the same time if they control the same
DAW or window.

First launch and permissions
----------------------------
Allow PressNext Live:
- "Accessibility" — for global hotkeys and window placement;
- control of QuickTime Player;
- control of Preview, TextEdit and System Events;
- control of the chosen DAW, if macOS asks for it.

After enabling Accessibility, quit PressNext Live completely and launch
it again.

Note: installing a new build of this package produces a new executable
with a new signature, and macOS sometimes silently resets the
Accessibility permission for it — PressNext Live still looks enabled in
the list, but commands do not actually get through. If window placement
stops working after an update, open "System Settings -> Privacy &
Security -> Accessibility", remove PressNext Live with "−", launch it
again and grant access when the system asks.

Supported files
---------------
Audio: MP3, WAV.
Lyrics/image: PNG, JPG, JPEG, PDF, DOCX, TXT.

The lyrics file must sit next to the audio and share its name up to the
extension:

  01 - Song.wav
  01 - Song.pdf

Images and PDFs open in Preview, DOCX and TXT in TextEdit. The lyrics
window takes the chosen half of the screen ("Lyrics" menu); the QuickTime
Player window takes the opposite half — full width of the zone, and
vertically, depending on "Player view", either fully visible or with half
its height below the bottom screen edge (leaving the title bar and the
scrubber with the timing). This happens automatically, with no separate
setup. The lyrics file is optional: without it the song still plays. If
several files share the name, the first by priority is used:
PNG -> JPG -> JPEG -> PDF -> DOCX -> TXT.

Default controls
----------------
Left    back 10 seconds
Right   forward 10 seconds
Up      previous song
Down    next song
Esc     stop the song and close its windows
Space   pause / resume from the same spot
Cmd+Down   QuickTime volume down 2 dB
Cmd+Up     QuickTime volume up 2 dB
Cmd+O   close the current song and open the file chooser
Cmd+Q   close its own windows and quit PressNext Live

Rapid repeated Left/Right presses combine into one safe command. Three
quick Right presses, for example, seek 30 seconds forward.

"Pedalboard app" menu
---------------------
"Activate after start" turns the DAW hand-off on or off. Choose Logic
Pro, MainStage, Gig Performer or REAPER. "Choose another app…" accepts
any .app file, including a renamed one. The setting is remembered.

After a song opens, PressNext Live begins a verified activation of the
chosen program almost immediately: a first attempt after 50 ms, then
short retries if macOS has not switched focus yet. This does not
interrupt playback.

"Lyrics" menu
-------------
"Left" and "Right" take the corresponding half of the main screen.
"Second display" expands the lyrics window to the available area of the
second display. Without a second display, the left half of the main
screen is used.

"Player view" menu
------------------
"Whole window" shows the entire QuickTime window. "Top of window
(scrubber only)" moves half of it below the bottom screen edge, leaving
the title bar and the scrubber with the timing. Either way the window
takes the half of the screen opposite the lyrics, so the two never
overlap. The choice is remembered between launches.

"Hotkeys" menu
--------------
Every action can be reassigned. Arrows, Esc, Space, Return, Tab,
Home/End, Page Up/Page Down, F1–F12, letters and Command variants are
available. One key cannot be assigned to two actions. "Restore default
hotkeys" resets the whole set.

Assigned keys work while the front window belongs to PressNext Live,
QuickTime Player, Preview, TextEdit or the chosen DAW. The global monitor
in PressNext Live cannot stop the DAW from receiving the same key as
well. If Space or the arrows do something unwanted in the DAW, remove
that assignment in the DAW's own hotkey settings, or choose a different
key in PressNext Live.

"Batch format lyrics" menu
--------------------------
Turns lyrics text files (TXT, DOCX, RTF) into ready-made images for
on-stage display — one 1400x1960 px image (half a screen) per file, with
the text sized to the largest readable size. Image margins are 8 px on
each side, so the text fills practically the whole frame.
The result is saved under the same name as the source file, so it can be
placed next to the audio right away — PressNext Live will pick it up as
an ordinary companion file for the song (see "Supported files" above).

Menu items:
  Choose files…               — pick one or more lyrics files
  Choose font…                — opens the system font panel
  Save folder…                — where to save the finished images
  Save format                 — PNG, JPG or PDF
  Verse color… / Chorus color… / Bridge color… — open the system color
                                 picker
  Start formatting            — processes all selected files

Formatting:
  - Text is drawn white and in CAPITALS by default. The default font is
    Bebas Neue if installed; otherwise the closest narrow/bold system
    font is used. Your own font can be chosen via "Choose font…".
  - The chorus is shown in full only on its first appearance; after that
    it becomes +CHORUS (or +CHORUS*3 if it repeats several times in a row
    verbatim); the same for the bridge (+BRIDGE). A repeat with small
    differences from the first appearance (tolerance depends on stanza
    length: roughly 15 characters, but no more than 20% of its length,
    ignoring case and punctuation) gives +VAR CHORUS/+VAR BRIDGE instead
    of +CHORUS/+BRIDGE — a signal that the words differ slightly and are
    worth a look. Choruses/bridges with different text (a second chorus
    variant, say) are tracked separately from each other. The label is
    always appended to the end of the previous line rather than put on a
    new one; if it does not fit there, it moves to its own line.
  - Several consecutive short lines are merged into one with triple
    spaces; consecutive identical words collapse into WORD*4; a long
    melisma over 2+ lines (oooh, a-ah-a and so on) is replaced with the
    word VOCALISE.
  - The finished image is compressed to roughly 200-300 KB (for PNG the
    size usually fits the budget anyway thanks to flat colors; for
    JPG/PDF the quality is chosen automatically).

Stanza detection: if the text file contains [Chorus] and/or [Bridge]
markers (in brackets, with or without a colon, with a number, with "x2"
or "(2 times)", case-insensitive), those are used, and this is the most
reliable option. A marker may be on its own line or in front of the text
on the same line ("Chorus: my light"). The earliest appearance of a
section is shown in full; all other repeats of that same text are found
across the whole song automatically — below and above the marker, even if
unmarked themselves. A lone "Chorus" line between verses is read as an
instruction to repeat the chorus and gives +CHORUS (with "(2 times)" —
+CHORUS*2). [Verse] is recognised too, but only so it is not confused
with a chorus or bridge; on its own it changes nothing. "Intro",
"Instrumental", "Solo", "Coda" and verse numbering ("1.", "2)") are
stripped from the text and serve only as stanza separators.

Blank lines between stanzas are desirable but not required: markers split
the text by themselves, and where there are no markers at all the app
looks for repeating blocks of lines and cuts the song along them.

If only the chorus or only the bridge is marked, the missing one is found
heuristically: PressNext Live looks for repeating blocks of text among
the unmarked paragraphs and treats them as the missing marker. If neither
is marked, PressNext Live searches the whole file for repeats in the same
way, but every repeating block found is treated as the chorus (with no
chorus/bridge split). This is a heuristic and can be wrong on an unusual
song structure — in which case it is easier to add markers to the file.

If there are no markers at all and no repeating blocks are found (a song
with no clear chorus or bridge), PressNext Live colors the paragraphs in
rotation for readability: white, light blue, light green — instead of one
solid color for every verse.

Closing and safety
------------------
When switching songs, PressNext Live first closes and verifies the old
documents, and only then opens the new ones. Documents are tracked by ID
and full path, which protects against problems with special characters in
names. After a song ends naturally, PressNext Live closes the documents
it opened and quits QuickTime/Preview/TextEdit only when no other
documents are left in that application. PressNext Live is then activated
again.
